package map.areaeffect;

import loadsave.LoadSaveable;
import loadsave.Memento;
import loadsave.loadsaveobject.LoadSaveObject;
import loadsave.loadsaveobject.LoadSaveObjectComposite;
import loadsave.loadsaveobject.LoadSavePrimitive;
import map.GameWorld;
import scheduler.DuplicateEventException;
import scheduler.Notifiable;
import scheduler.Scheduler;
import effects.Effect;
import entity.Entity;
import entity.Entity.EffectVisitor;
import factory.AEFactory;

public class AreaEffectApplier implements LoadSaveable {
	
	private Notifiable scheduled;
	private AreaEffect areaEffect;
	private Entity entity;
	
	public AreaEffectApplier() {
		
		areaEffect = null;
		entity = null;
	}
	
	public AreaEffectApplier(AreaEffect areaEffect, Entity entity) {
		
		this.areaEffect = areaEffect;
		this.entity = entity;
	}
	
	public void schedule() {
		
		//do scheduling stuff
		try {
			Scheduler.getInstance().schedule((scheduled = new Notifiable() {

				@Override
				public void execute() {
					EffectVisitor ev =  entity.getEffectVisitor();
					Effect e = areaEffect.getEffect();
					e.accept(ev);
				}
				
			}), areaEffect.getRate());
		} catch (DuplicateEventException e) {
			e.printStackTrace();
		}
	}
	
	public void unschedule() {
		Scheduler.getInstance().cancel(scheduled);
		scheduled = null;
	}

	@Override
	public Memento getMemento() {
		return new Memento() {

			@Override
			public LoadSaveObject getState() {
				LoadSaveObjectComposite toReturn = new LoadSaveObjectComposite("", "AreaEffectApplier");
				LoadSaveObject lso = areaEffect.getMemento().getState();
				lso.setName("areaEffect");
				toReturn.add(lso.getName(), lso);
				lso = entity.getMemento().getState();
				lso.setName("entity");
				toReturn.add(lso.getName(), lso);
				toReturn.add("scheduled", new LoadSavePrimitive("scheduled", "boolean", String.valueOf(scheduled == null)));
				return toReturn;
			}

			@Override
			public void restoreState(LoadSaveObject lso) {
				areaEffect = AEFactory.createAreaEffect(lso.get("areaEffect"));
				entity = GameWorld.getInstance().getEntity(lso.get("entity").get("name").getValue());
				if (Boolean.valueOf(lso.get("scheduled").getValue())) {
					schedule();
				}
			}
			
		};
	}
	

}
